home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / ed.chared.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  57.1 KB  |  3,159 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/ed.chared.c,v 3.18 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * ed.chared.c: Character editing functions.
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: ed.chared.c,v 3.18 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tw.h"
  43. #include "ed.defns.h"
  44.  
  45. /* #define SDEBUG */
  46.  
  47. #define NOP          0x00
  48. #define DELETE       0x01
  49. #define INSERT       0x02
  50. #define CHANGE       0x04
  51.  
  52. #define CHAR_FWD    0
  53. #define CHAR_BACK    1
  54.  
  55. static Char *InsertPos = InputBuf; /* Where insertion starts */
  56. static Char *ActionPos = 0;       /* Where action begins  */
  57. static int  ActionFlag = NOP;       /* What delayed action to take */
  58. /*
  59.  * Word search state
  60.  */
  61. static int  searchdir = F_UP_SEARCH_HIST;     /* Direction of last search */
  62. static Char patbuf[INBUFSIZE];            /* Search target */
  63. static int patlen = 0;
  64. /*
  65.  * Char search state
  66.  */
  67. static int  srch_dir = CHAR_FWD;        /* Direction of last search */
  68. static Char srch_char = 0;            /* Search target */
  69.  
  70. /* all routines that start with c_ are private to this set of routines */
  71. static    void     c_alternativ_key_map    __P((int));
  72. static    void     c_insert        __P((int));
  73. static    void     c_delafter        __P((int));
  74. static    void     c_delbefore        __P((int));
  75. static    Char    *c_prev_word        __P((Char *, Char *, int));
  76. static    Char    *c_next_word        __P((Char *, Char *, int));
  77. static    void     c_copy            __P((Char *, Char *, int));
  78. static    Char    *c_number        __P((Char *, int *, int));
  79. static    Char    *c_expand        __P((Char *));
  80. static    void     c_excl            __P((Char *));
  81. static    void     c_substitute        __P((void));
  82. static    int     c_hmatch        __P((Char *));
  83. static    void     c_hsetpat        __P((void));
  84. #ifdef COMMENT
  85. static    void     c_get_word        __P((Char **, Char **));
  86. #endif
  87. static    Char    *c_preword        __P((Char *, Char *, int));
  88. static    Char    *c_nexword        __P((Char *, Char *, int));
  89. static    Char    *c_endword        __P((Char *, Char *, int));
  90. static    Char    *c_eword        __P((Char *, Char *, int));
  91. static  CCRETVAL c_get_histline        __P((void));
  92. static  CCRETVAL c_search_line        __P((Char *, int));
  93. static  CCRETVAL v_repeat_srch        __P((int));
  94. static    CCRETVAL e_inc_search        __P((int));
  95. static    CCRETVAL v_search        __P((int));
  96. static    CCRETVAL v_csearch_fwd        __P((int, int, int));
  97. static    CCRETVAL v_csearch_back        __P((int, int, int));
  98.  
  99. static void
  100. c_alternativ_key_map(state)
  101.     int     state;
  102. {
  103.     switch (state) {
  104.     case 0:
  105.     CurrentKeyMap = CcKeyMap;
  106.     break;
  107.     case 1:
  108.     CurrentKeyMap = CcAltMap;
  109.     break;
  110.     default:
  111.     return;
  112.     }
  113.  
  114.     AltKeyMap = state;
  115. }
  116.  
  117. static void
  118. c_insert(num)
  119.     register int num;
  120. {
  121.     register Char *cp;
  122.  
  123.     if (LastChar + num >= InputLim)
  124.     return;            /* can't go past end of buffer */
  125.  
  126.     if (Cursor < LastChar) {    /* if I must move chars */
  127.     for (cp = LastChar; cp >= Cursor; cp--)
  128.         cp[num] = *cp;
  129.     }
  130.     LastChar += num;
  131. }
  132.  
  133. static void
  134. c_delafter(num)    
  135.     register int num;
  136. {
  137.     register Char *cp, *kp;
  138.  
  139.     if (Cursor + num > LastChar)
  140.     num = LastChar - Cursor;    /* bounds check */
  141.  
  142.     if (num > 0) {            /* if I can delete anything */
  143.     if (VImode) {
  144.         kp = UndoBuf;        /* Set Up for VI undo command */
  145.         UndoAction = INSERT;
  146.         UndoSize = num;
  147.         UndoPtr  = Cursor;
  148.         for (cp = Cursor; cp <= LastChar; cp++) {
  149.         *kp++ = *cp;    /* Save deleted chars into undobuf */
  150.         *cp = cp[num];
  151.         }
  152.     }
  153.     else
  154.         for (cp = Cursor; cp <= LastChar; cp++)
  155.         *cp = cp[num];
  156.     LastChar -= num;
  157.     }
  158. #ifdef notdef
  159.     else {
  160.     /* 
  161.      * XXX: We don't want to do that. In emacs mode overwrite should be
  162.      * sticky. I am not sure how that affects vi mode 
  163.      */
  164.     inputmode = MODE_INSERT;
  165.     }
  166. #endif /* notdef */
  167. }
  168.  
  169. static void
  170. c_delbefore(num)        /* delete before dot, with bounds checking */
  171.     register int num;
  172. {
  173.     register Char *cp, *kp;
  174.  
  175.     if (Cursor - num < InputBuf)
  176.     num = Cursor - InputBuf;    /* bounds check */
  177.  
  178.     if (num > 0) {            /* if I can delete anything */
  179.     if (VImode) {
  180.         kp = UndoBuf;        /* Set Up for VI undo command */
  181.         UndoAction = INSERT;
  182.         UndoSize = num;
  183.         UndoPtr  = Cursor - num;
  184.         for (cp = Cursor - num; cp <= LastChar; cp++) {
  185.         *kp++ = *cp;
  186.         *cp = cp[num];
  187.         }
  188.     }
  189.     else
  190.         for (cp = Cursor - num; cp <= LastChar; cp++)
  191.         *cp = cp[num];
  192.     LastChar -= num;
  193.     }
  194. }
  195.  
  196. static Char *
  197. c_preword(p, low, n)
  198.     register Char *p, *low;
  199.     register int n;
  200. {
  201.     p--;
  202.  
  203.     while (n--) {
  204.     while ((p >= low) && Isspace(*p)) 
  205.         p--;
  206.     while ((p >= low) && !Isspace(*p)) 
  207.         p--;
  208.     }
  209.     /* cp now points to one character before the word */
  210.     p++;
  211.     if (p < low)
  212.     p = low;
  213.     /* cp now points where we want it */
  214.     return(p);
  215. }
  216.  
  217. static Char *
  218. c_prev_word(p, low, n)
  219.     register Char *p, *low;
  220.     register int n;
  221. {
  222.     p--;
  223.  
  224.     while (n--) {
  225.     while ((p >= low) && !isword(*p)) 
  226.         p--;
  227.     while ((p >= low) && isword(*p)) 
  228.         p--;
  229.     }
  230.  
  231.     /* cp now points to one character before the word */
  232.     p++;
  233.     if (p < low)
  234.     p = low;
  235.     /* cp now points where we want it */
  236.     return(p);
  237. }
  238.  
  239. static Char *
  240. c_next_word(p, high, n)
  241.     register Char *p, *high;
  242.     register int n;
  243. {
  244.     while (n--) {
  245.     while ((p < high) && !isword(*p)) 
  246.         p++;
  247.     while ((p < high) && isword(*p)) 
  248.         p++;
  249.     }
  250.     if (p > high)
  251.     p = high;
  252.     /* p now points where we want it */
  253.     return(p);
  254. }
  255.  
  256. static Char *
  257. c_nexword(p, high, n)
  258.     register Char *p, *high;
  259.     register int n;
  260. {
  261.     while (n--) {
  262.     while ((p < high) && !Isspace(*p)) 
  263.         p++;
  264.     while ((p < high) && Isspace(*p)) 
  265.         p++;
  266.     }
  267.  
  268.     if (p > high)
  269.     p = high;
  270.     /* p now points where we want it */
  271.     return(p);
  272. }
  273.  
  274. /*
  275.  * Expand-History (originally "Magic-Space") code added by
  276.  * Ray Moody <ray@gibbs.physics.purdue.edu>
  277.  * this is a neat, but odd, addition.
  278.  */
  279.  
  280. /*
  281.  * c_copy is sorta like bcopy() except that we handle overlap between
  282.  * source and destination memory
  283.  */
  284.  
  285. static void
  286. c_copy(src, dst, length)
  287.     register Char *src, *dst;
  288.     register int length;
  289. {
  290.     if (src > dst) {
  291.     while (length--) {
  292.         *dst++ = *src++;
  293.     }
  294.     }
  295.     else {
  296.     src += length;
  297.     dst += length;
  298.     while (length--) {
  299.         *--dst = *--src;
  300.     }
  301.     }
  302. }
  303.  
  304. /*
  305.  * c_number: Ignore character p points to, return number appearing after that.
  306.  * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
  307.  * Return p pointing to last char used.
  308.  */
  309.  
  310. /*
  311.  * dval is the number to subtract from for things like $-3
  312.  */
  313.  
  314. static Char *
  315. c_number(p, num, dval)
  316.     register Char *p;
  317.     register int *num;
  318.     register int dval;
  319. {
  320.     register int i;
  321.     register int sign = 1;
  322.  
  323.     if (*++p == '^') {
  324.     *num = 1;
  325.     return(p);
  326.     }
  327.     if (*p == '$') {
  328.     if (*++p != '-') {
  329.         *num = NCARGS;    /* Handle $ */
  330.         return(--p);
  331.     }
  332.     sign = -1;        /* Handle $- */
  333.     ++p;
  334.     }
  335.     for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0');
  336.     *num = (sign < 0 ? dval - i : i);
  337.     return(--p);
  338. }
  339.  
  340. /*
  341.  * excl_expand: There is an excl to be expanded to p -- do the right thing
  342.  * with it and return a version of p advanced over the expanded stuff.  Also,
  343.  * update tsh_cur and related things as appropriate...
  344.  */
  345.  
  346. static Char *
  347. c_expand(p)
  348.     register Char *p;
  349. {
  350.     register Char *q;
  351.     register struct Hist *h = Histlist.Hnext;
  352.     register struct wordent *l;
  353.     int     i, from, to, dval;
  354.     bool    all_dig;
  355.     bool    been_once = 0;
  356.     Char   *op = p;
  357.     Char    buf[INBUFSIZE];
  358.     Char   *bend = buf;
  359.     Char   *modbuf, *omodbuf;
  360.  
  361.     if (!h)
  362.     goto excl_err;
  363. excl_sw:
  364.     switch (*(q = p + 1)) {
  365.  
  366.     case '^':
  367.     bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
  368.     break;
  369.  
  370.     case '$':
  371.     if ((l = (h->Hlex).prev))
  372.         bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
  373.     break;
  374.  
  375.     case '*':
  376.     bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
  377.     break;
  378.  
  379.     default:
  380.     if (been_once) {    /* unknown argument */
  381.         /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
  382.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
  383.         q -= 2;
  384.         break;
  385.     }
  386.     been_once = 1;
  387.  
  388.     if (*q == ':')        /* short form: !:arg */
  389.         --q;
  390.  
  391.     if (*q != HIST) {
  392.         /*
  393.          * Search for a space, tab, or colon.  See if we have a number (as
  394.          * in !1234:xyz).  Remember the number.
  395.          */
  396.         for (i = 0, all_dig = 1; 
  397.          *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
  398.         /*
  399.          * PWP: !-4 is a valid history argument too, therefore the test
  400.          * is if not a digit, or not a - as the first character.
  401.          */
  402.         if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
  403.             all_dig = 0;
  404.         else if (*q == '-')
  405.             all_dig = 2;/* we are sneeky about this */
  406.         else
  407.             i = 10 * i + *q - '0';
  408.         }
  409.         --q;
  410.  
  411.         /*
  412.          * If we have a number, search for event i.  Otherwise, search for
  413.          * a named event (as in !foo).  (In this case, I is the length of
  414.          * the named event).
  415.          */
  416.         if (all_dig) {
  417.         if (all_dig == 2)
  418.             i = -i;    /* make it negitive */
  419.         if (i < 0)    /* if !-4 (for example) */
  420.             i = eventno + 1 + i;    /* remember: i is < 0 */
  421.         for (; h; h = h->Hnext) {
  422.             if (h->Hnum == i)
  423.             break;
  424.         }
  425.         }
  426.         else {
  427.         for (i = q - p; h; h = h->Hnext) {
  428.             if ((l = &h->Hlex)) {
  429.             if (!Strncmp(p + 1, l->next->word, i))
  430.                 break;
  431.             }
  432.         }
  433.         }
  434.     }
  435.     if (!h)
  436.         goto excl_err;
  437.     if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
  438.         q[1] == '$' || q[1] == '^') {    /* get some args */
  439.         p = q[1] == ':' ? ++q : q;
  440.         /*
  441.          * Go handle !foo:*
  442.          */
  443.         if ((q[1] < '0' || q[1] > '9') &&
  444.         q[1] != '-' && q[1] != '$' && q[1] != '^')
  445.         goto excl_sw;
  446.         /*
  447.          * Go handle !foo:$
  448.          */
  449.         if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
  450.         goto excl_sw;
  451.         /*
  452.          * Count up the number of words in this event.  Store it in dval.
  453.          * Dval will be fed to number.
  454.          */
  455.         dval = 0;
  456.         if ((l = h->Hlex.prev)) {
  457.         for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++);
  458.         }
  459.         if (!dval)
  460.         goto excl_err;
  461.         if (q[1] == '-')
  462.         from = 0;
  463.         else
  464.         q = c_number(q, &from, dval);
  465.         if (q[1] == '-') {
  466.         ++q;
  467.         if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
  468.             to = dval - 1;
  469.         else
  470.             q = c_number(q, &to, dval);
  471.         }
  472.         else if (q[1] == '*') {
  473.         ++q;
  474.         to = NCARGS;
  475.         }
  476.         else {
  477.         to = from;
  478.         }
  479.         if (from < 0 || to < from)
  480.         goto excl_err;
  481.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
  482.     }
  483.     else {            /* get whole cmd */
  484.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
  485.     }
  486.     break;
  487.     }
  488.  
  489.     /*
  490.      * Apply modifiers, if any.
  491.      */
  492.     if (q[1] == ':') {
  493.     *bend = '\0';
  494.     omodbuf = buf;
  495.     while (q[1] == ':' && (modbuf = domod(omodbuf, (int) q[2])) != NULL) {
  496.         if (omodbuf != buf)
  497.         xfree((ptr_t) omodbuf);
  498.         omodbuf = modbuf;
  499.         q += 2;
  500.     }
  501.     if (omodbuf != buf) {
  502.         (void) Strcpy(buf, omodbuf);
  503.         xfree((ptr_t) omodbuf);
  504.         bend = Strend(buf);
  505.     }
  506.     }
  507.  
  508.     /*
  509.      * Now replace the text from op to q inclusive with the text from buf to
  510.      * bend.
  511.      */
  512.     q++;
  513.  
  514.     /*
  515.      * Now replace text non-inclusively like a real CS major!
  516.      */
  517.     if (LastChar + (bend - buf) - (q - op) >= InputLim)
  518.     goto excl_err;
  519.     c_copy(q, q + (bend - buf) - (q - op), LastChar - q);
  520.     LastChar += (bend - buf) - (q - op);
  521.     Cursor += (bend - buf) - (q - op);
  522.     c_copy(buf, op, (bend - buf));
  523.     return(op + (bend - buf));
  524. excl_err:
  525.     Beep();
  526.     return(op + 1);
  527. }
  528.  
  529. /*
  530.  * c_excl: An excl has been found at point p -- back up and find some white
  531.  * space (or the beginning of the buffer) and properly expand all the excl's
  532.  * from there up to the current cursor position. We also avoid (trying to)
  533.  * expanding '>!'
  534.  */
  535.  
  536. static void
  537. c_excl(p)
  538.     register Char *p;
  539. {
  540.     register int i;
  541.     register Char *q;
  542.  
  543.     /*
  544.      * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
  545.      * back p up to just before the current word.
  546.      */
  547.     if ((p[1] == ' ' || p[1] == '\t') &&
  548.     (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
  549.     for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q);
  550.     if (*q == '>')
  551.         ++p;
  552.     }
  553.     else {
  554.     while (*p != ' ' && *p != '\t' && p > InputBuf)
  555.         --p;
  556.     }
  557.  
  558.     /*
  559.      * Forever: Look for history char.  (Stop looking when we find the cursor.)
  560.      * Count backslashes.  Of odd, skip history char. Return if all done.
  561.      * Expand if even number of backslashes.
  562.      */
  563.     for (;;) {
  564.     while (*p != HIST && p < Cursor)
  565.         ++p;
  566.     for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++);
  567.     if (i % 2 == 0)
  568.         ++p;
  569.     if (p >= Cursor)
  570.         return;
  571.     if (i % 2 == 1)
  572.         p = c_expand(p);
  573.     }
  574. }
  575.  
  576.  
  577. static void
  578. c_substitute()
  579. {
  580.     register Char *p;
  581.  
  582.     /*
  583.      * Start p out one character before the cursor.  Move it backwards looking
  584.      * for white space, the beginning of the line, or a history character.
  585.      */
  586.     for (p = Cursor - 1; 
  587.      p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p);
  588.  
  589.     /*
  590.      * If we found a history character, go expand it.
  591.      */
  592.     if (*p == HIST)
  593.     c_excl(p);
  594.     Refresh();
  595. }
  596.  
  597. static void
  598. c_delfini()        /* Finish up delete action */
  599. {
  600.     register int Size;
  601.  
  602.     if (ActionFlag & INSERT)
  603.     c_alternativ_key_map(0);
  604.  
  605.     ActionFlag = NOP;
  606.  
  607.     if (ActionPos == 0) 
  608.     return;
  609.  
  610.     UndoAction = INSERT;
  611.  
  612.     if (Cursor > ActionPos) {
  613.     Size = (int) (Cursor-ActionPos);
  614.     c_delbefore(Size); 
  615.     Cursor = ActionPos;
  616.     RefCursor();
  617.     }
  618.     else if (Cursor < ActionPos) {
  619.     Size = (int)(ActionPos-Cursor);
  620.     c_delafter(Size);
  621.     }
  622.     else  {
  623.     Size = 1;
  624.     c_delafter(Size);
  625.     }
  626.     UndoPtr = Cursor;
  627.     UndoSize = Size;
  628. }
  629.  
  630. static Char *
  631. c_endword(p, high, n)
  632.     register Char *p, *high;
  633.     register int n;
  634. {
  635.     p++;
  636.  
  637.     while (n--) {
  638.     while ((p < high) && Isspace(*p))
  639.         p++;
  640.     while ((p < high) && !Isspace(*p)) 
  641.         p++;
  642.     }
  643.  
  644.     p--;
  645.     return(p);
  646. }
  647.  
  648.  
  649. static Char *
  650. c_eword(p, high, n)
  651.     register Char *p, *high;
  652.     register int n;
  653. {
  654.     p++;
  655.  
  656.     while (n--) {
  657.     while ((p < high) && Isspace(*p)) 
  658.         p++;
  659.  
  660.     if (Isalnum(*p))
  661.         while ((p < high) && Isalnum(*p)) 
  662.         p++;
  663.     else
  664.         while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
  665.         p++;
  666.     }
  667.  
  668.     p--;
  669.     return(p);
  670. }
  671.  
  672. static CCRETVAL
  673. c_get_histline()
  674. {
  675.     struct Hist *hp;
  676.     int     h;
  677.  
  678.     if (Hist_num == 0) {    /* if really the current line */
  679.     copyn(InputBuf, HistBuf, INBUFSIZE);
  680.     LastChar = InputBuf + (LastHist - HistBuf);
  681.  
  682. #ifdef KSHVI
  683.     if (VImode)
  684.     Cursor = InputBuf;
  685.     else
  686. #endif /* KSHVI */
  687.     Cursor = LastChar;
  688.  
  689.     return(CC_REFRESH);
  690.     }
  691.  
  692.     hp = Histlist.Hnext;
  693.     if (hp == NULL)
  694.     return(CC_ERROR);
  695.  
  696.     for (h = 1; h < Hist_num; h++) {
  697.     if ((hp->Hnext) == NULL) {
  698.         Hist_num = h;
  699.         return(CC_ERROR);
  700.     }
  701.     hp = hp->Hnext;
  702.     }
  703.  
  704.     if (HistLit && hp->histline) {
  705.     copyn(InputBuf, hp->histline, INBUFSIZE);
  706.     CurrentHistLit = 1;
  707.     }
  708.     else {
  709.     (void) sprlex(InputBuf, &hp->Hlex);
  710.     CurrentHistLit = 0;
  711.     }
  712.     LastChar = InputBuf + Strlen(InputBuf);
  713.  
  714.     if (LastChar > InputBuf) {
  715.     if (LastChar[-1] == '\n')
  716.         LastChar--;
  717.     if (LastChar[-1] == ' ')
  718.         LastChar--;
  719.     if (LastChar < InputBuf)
  720.         LastChar = InputBuf;
  721.     }
  722.  
  723. #ifdef KSHVI
  724.     if (VImode)
  725.     Cursor = InputBuf;
  726.     else
  727. #endif /* KSHVI */
  728.     Cursor = LastChar;
  729.  
  730.     return(CC_REFRESH);
  731. }
  732.  
  733. static CCRETVAL
  734. c_search_line(pattern, dir)
  735. Char *pattern;
  736. int dir;
  737. {
  738.     Char *cp;
  739.     int len;
  740.  
  741.     len = Strlen(pattern);
  742.  
  743.     if (dir == F_UP_SEARCH_HIST) {
  744.     for (cp = Cursor; cp >= InputBuf; cp--)
  745.         if (Strncmp(cp, pattern, len) == 0 || Gmatch(cp, pattern)) {
  746.         Cursor = cp;
  747.         return(CC_NORM);
  748.         }
  749.     return(CC_ERROR);
  750.     } else {
  751.     for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
  752.         if (Strncmp(cp, pattern, len) == 0 || Gmatch(cp, pattern)) {
  753.         Cursor = cp;
  754.         return(CC_NORM);
  755.         }
  756.     return(CC_ERROR);
  757.     }
  758. }
  759.  
  760. static CCRETVAL
  761. e_inc_search(dir)
  762.     int dir;
  763. {
  764.     static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
  765.         STRbck[] = { 'b', 'c', 'k', '\0' };
  766.     static Char pchar = ':';    /* ':' = normal, '?' = failed */
  767.     static Char endcmd[2];
  768.     Char ch, *cp,
  769.     *oldCursor = Cursor,
  770.     oldpchar = pchar;
  771.     CCRETVAL ret = CC_NORM;
  772.     int oldHist_num = Hist_num,
  773.     oldpatlen = patlen,
  774.     newdir = dir,
  775.         done, redo;
  776.  
  777.     if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
  778.     return(CC_ERROR);
  779.  
  780.     for (;;) {
  781.  
  782.     if (patlen == 0) {    /* first round */
  783.         pchar = ':';
  784.         patbuf[patlen++] = '*';
  785.     }
  786.     done = redo = 0;
  787.     *LastChar++ = '\n';
  788.     for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd; 
  789.          *cp; *LastChar++ = *cp++);
  790.     *LastChar++ = pchar;
  791.     for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++);
  792.     *LastChar = '\0';
  793.     Refresh();
  794.  
  795.     if (GetNextChar(&ch) != 1)
  796.         return(e_send_eof(0));
  797.  
  798.     switch (CurrentKeyMap[(unsigned char) ch]) {
  799.     case F_INSERT:
  800.     case F_DIGIT:
  801.     case F_MAGIC_SPACE:
  802.         if (patlen > INBUFSIZE - 3)
  803.         Beep();
  804.         else {
  805.         patbuf[patlen++] = ch;
  806.         *LastChar++ = ch;
  807.         *LastChar = '\0';
  808.         Refresh();
  809.         }
  810.         break;
  811.  
  812.     case F_INC_FWD:
  813.         newdir = F_DOWN_SEARCH_HIST;
  814.         redo++;
  815.         break;
  816.  
  817.     case F_INC_BACK:
  818.         newdir = F_UP_SEARCH_HIST;
  819.         redo++;
  820.         break;
  821.  
  822.     case F_DELPREV:
  823.         if (patlen > 1)
  824.         done++;
  825.         else 
  826.         Beep();
  827.         break;
  828.  
  829.     default:
  830.         switch (ch) {
  831.         case 0007:        /* ^G: Abort */
  832.         ret = CC_ERROR;
  833.         done++;
  834.         break;
  835.  
  836.         case 0027:        /* ^W: Append word */
  837.         /* No can do if globbing characters in pattern */
  838.         for (cp = &patbuf[1]; ; cp++)
  839.             if (cp >= &patbuf[patlen]) {
  840.             Cursor += patlen - 1;
  841.             cp = c_next_word(Cursor, LastChar, 1);
  842.             while (Cursor < cp && *Cursor != '\n') {
  843.                 if (patlen > INBUFSIZE - 3) {
  844.                 Beep();
  845.                 break;
  846.                 }
  847.                 patbuf[patlen++] = *Cursor;
  848.                 *LastChar++ = *Cursor++;
  849.             }
  850.             Cursor = oldCursor;
  851.             *LastChar = '\0';
  852.             Refresh();
  853.             break;
  854.             } else if (isglob(*cp)) {
  855.             Beep();
  856.             break;
  857.             }
  858.         break;
  859.         
  860.         default:        /* Terminate and execute cmd */
  861.         endcmd[0] = ch;
  862.         PushMacro(endcmd);
  863.         /* fall through */
  864.  
  865.         case 0033:        /* ESC: Terminate */
  866.         ret = CC_REFRESH;
  867.         done++;
  868.         break;
  869.         }
  870.         break;
  871.     }
  872.  
  873.     while (LastChar > InputBuf && *LastChar != '\n')
  874.         *LastChar-- = '\0';
  875.     *LastChar = '\0';
  876.  
  877.     if (!done) {
  878.  
  879.         /* Can't search if unmatched '[' */
  880.         for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
  881.         if (*cp == '[' || *cp == ']') {
  882.             ch = *cp;
  883.             break;
  884.         }
  885.  
  886.         if (patlen > 1 && ch != '[') {
  887.         if (redo && newdir == dir) {
  888.             if (pchar == '?') {    /* wrap around */
  889.             Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
  890.             if (c_get_histline() == CC_ERROR)
  891.                 /* Hist_num was fixed by first call */
  892.                 (void) c_get_histline();
  893.             Cursor = newdir == F_UP_SEARCH_HIST ?
  894.                 LastChar : InputBuf;
  895.             } else
  896.             Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
  897.         }
  898.         patbuf[patlen++] = '*';
  899.         patbuf[patlen] = '\0';
  900.         if (Cursor < InputBuf || Cursor > LastChar ||
  901.             (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
  902.             LastCmd = newdir; /* avoid c_hsetpat */
  903.             ret = newdir == F_UP_SEARCH_HIST ?
  904.             e_up_search_hist(0) : e_down_search_hist(0);
  905.             if (ret != CC_ERROR) {
  906.             Cursor = newdir == F_UP_SEARCH_HIST ?
  907.                 LastChar : InputBuf;
  908.             (void) c_search_line(&patbuf[1], newdir);
  909.             }
  910.         }
  911.         patbuf[--patlen] = '\0';
  912.         if (ret == CC_ERROR) {
  913.             Beep();
  914.             if (Hist_num != oldHist_num) {
  915.             Hist_num = oldHist_num;
  916.             if (c_get_histline() == CC_ERROR)
  917.                 return(CC_ERROR);
  918.             }
  919.             Cursor = oldCursor;
  920.             pchar = '?';
  921.         } else {
  922.             pchar = ':';
  923.         }
  924.         }
  925.  
  926.         ret = e_inc_search(newdir);
  927.  
  928.         if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
  929.         /* break abort of failed search at last non-failed */
  930.         ret = CC_NORM;
  931.         }
  932.  
  933.     }
  934.  
  935.     if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
  936.         /* restore on normal return or error exit */
  937.         pchar = oldpchar;
  938.         patlen = oldpatlen;
  939.         if (Hist_num != oldHist_num) {
  940.         Hist_num = oldHist_num;
  941.         if (c_get_histline() == CC_ERROR)
  942.             return(CC_ERROR);
  943.         }
  944.         Cursor = oldCursor;
  945.         if (ret == CC_ERROR)
  946.         Refresh();
  947.     }
  948.     if (done || ret != CC_NORM)
  949.         return(ret);
  950.         
  951.     }
  952.  
  953. }
  954.  
  955. static CCRETVAL
  956. v_search(dir)
  957.     int dir;
  958. {
  959.     Char ch;
  960.     Char tmpbuf[INBUFSIZE];
  961.     int tmplen;
  962.  
  963.     tmplen = 0;
  964.     tmpbuf[tmplen++] = '*';
  965.  
  966.     InputBuf[0] = '\0';
  967.     LastChar = InputBuf;
  968.     Cursor = InputBuf;
  969.     searchdir = dir;
  970.  
  971.     c_insert(2);    /* prompt + '\n' */
  972.     *Cursor++ = '\n';
  973.     *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
  974.     Refresh();
  975.     for (ch = 0;ch == 0;) {
  976.     if (GetNextChar(&ch) != 1)
  977.         return(e_send_eof(0));
  978.     switch (ch) {
  979.     case 0010:    /* Delete and backspace */
  980.     case 0177:
  981.         if (tmplen > 1) {
  982.         *Cursor-- = '\0';
  983.         LastChar = Cursor;
  984.         tmpbuf[tmplen--] = '\0';
  985.         }
  986.         else {
  987.         InputBuf[0] = '\0';
  988.         LastChar = InputBuf;
  989.         Cursor = InputBuf;
  990.         return(CC_REFRESH);
  991.         }
  992.         Refresh();
  993.         ch = 0;
  994.         break;
  995.  
  996.     case 0033:    /* ESC */
  997.     case '\r':    /* Newline */
  998.     case '\n':
  999.         break;
  1000.  
  1001.     default:
  1002.         if (tmplen >= INBUFSIZE)
  1003.         Beep();
  1004.         else {
  1005.         tmpbuf[tmplen++] = ch;
  1006.         *Cursor++ = ch;
  1007.         LastChar = Cursor;
  1008.         }
  1009.         Refresh();
  1010.         ch = 0;
  1011.         break;
  1012.     }
  1013.     }
  1014.  
  1015.     if (tmplen == 1) {
  1016.     /*
  1017.      * Use the old pattern, but wild-card it.
  1018.      */
  1019.     if (patlen == 0) {
  1020.         InputBuf[0] = '\0';
  1021.         LastChar = InputBuf;
  1022.         Cursor = InputBuf;
  1023.         Refresh();
  1024.         return(CC_ERROR);
  1025.     }
  1026.     if (patbuf[0] != '*') {
  1027.         (void) Strcpy(tmpbuf, patbuf);
  1028.         patbuf[0] = '*';
  1029.         (void) Strcpy(&patbuf[1], tmpbuf);
  1030.         patlen++;
  1031.         patbuf[patlen++] = '*';
  1032.         patbuf[patlen] = '\0';
  1033.     }
  1034.     }
  1035.     else {
  1036.     tmpbuf[tmplen++] = '*';
  1037.     tmpbuf[tmplen] = '\0';
  1038.     (void) Strcpy(patbuf, tmpbuf);
  1039.     patlen = tmplen;
  1040.     }
  1041.     LastCmd = dir; /* avoid c_hsetpat */
  1042.     Cursor = LastChar = InputBuf;
  1043.     if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) : 
  1044.                    e_down_search_hist(0)) == CC_ERROR) {
  1045.     Refresh();
  1046.     return(CC_ERROR);
  1047.     }
  1048.     else {
  1049.     if (ch == 0033) {
  1050.         Refresh();
  1051.         *LastChar++ = '\n';
  1052.         *LastChar = '\0';
  1053.         PastBottom();
  1054.         return(CC_NEWLINE);
  1055.     }
  1056.     else
  1057.         return(CC_REFRESH);
  1058.     }
  1059. }
  1060.  
  1061. /*
  1062.  * semi-PUBLIC routines.  Any routine that is of type CCRETVAL is an
  1063.  * entry point, called from the CcKeyMap indirected into the
  1064.  * CcFuncTbl array.
  1065.  */
  1066.  
  1067. /*ARGSUSED*/
  1068. CCRETVAL
  1069. v_cmd_mode(c)
  1070.     int c;
  1071. {
  1072.  
  1073.     InsertPos = 0;
  1074.     ActionFlag = NOP;    /* [Esc] cancels pending action */
  1075.     ActionPos = 0;
  1076.     DoingArg = 0;
  1077.     if (UndoPtr > Cursor)
  1078.     UndoSize = (int)(UndoPtr - Cursor);
  1079.     else
  1080.     UndoSize = (int)(Cursor - UndoPtr);
  1081.  
  1082.     inputmode = MODE_INSERT;
  1083.     c_alternativ_key_map(1);
  1084. #ifdef notdef
  1085.     /*
  1086.      * We don't want to move the cursor, because all the editing
  1087.      * commands don't include the character under the cursor.
  1088.      */
  1089.     if (Cursor > InputBuf)
  1090.     Cursor--;
  1091. #endif
  1092.     RefCursor();
  1093.     return(CC_NORM);
  1094. }
  1095.  
  1096. /*ARGSUSED*/
  1097. CCRETVAL
  1098. e_unassigned(c)
  1099.     int c;
  1100. {                /* bound to keys that arn't really assigned */
  1101.     Beep();
  1102.     flush();
  1103.     return(CC_NORM);
  1104. }
  1105.  
  1106. CCRETVAL
  1107. e_insert(c)
  1108.     register int c;
  1109. {
  1110.     register int i;
  1111. #ifndef SHORT_STRINGS
  1112.     c &= ASCII;            /* no meta chars ever */
  1113. #endif
  1114.  
  1115.     if (!c)
  1116.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1117.  
  1118.     if (LastChar + Argument >= InputLim)
  1119.     return(CC_ERROR);    /* end of buffer space */
  1120.  
  1121.     if (Argument == 1) {      /* How was this optimized ???? */
  1122.  
  1123.     if (inputmode != MODE_INSERT) {
  1124.         UndoBuf[UndoSize++] = *Cursor;
  1125.         UndoBuf[UndoSize] = '\0';
  1126.         c_delafter(1);   /* Do NOT use the saving ONE */
  1127.         }
  1128.  
  1129.         c_insert(1);
  1130.  
  1131.     *Cursor++ = c;
  1132.     DoingArg = 0;        /* just in case */
  1133.     RefPlusOne();        /* fast refresh for one char. */
  1134.     }
  1135.     else {
  1136.     if (inputmode != MODE_INSERT) {
  1137.  
  1138.         for(i=0;i<Argument;i++) 
  1139.         UndoBuf[UndoSize++] = *(Cursor+i);
  1140.  
  1141.         UndoBuf[UndoSize] = '\0';
  1142.         c_delafter(Argument);   /* Do NOT use the saving ONE */
  1143.         }
  1144.  
  1145.         c_insert(Argument);
  1146.  
  1147.     while (Argument--)
  1148.         *Cursor++ = c;
  1149.     Refresh();
  1150.     }
  1151.  
  1152.     if (inputmode == MODE_REPLACE_1)
  1153.     (void) v_cmd_mode(0);
  1154.  
  1155.     return(CC_NORM);
  1156. }
  1157.  
  1158. int
  1159. InsertStr(s)            /* insert ASCIZ s at cursor (for complete) */
  1160.     Char   *s;
  1161. {
  1162.     register int len;
  1163.  
  1164.     if ((len = Strlen(s)) <= 0)
  1165.     return -1;
  1166.     if (LastChar + len >= InputLim)
  1167.     return -1;        /* end of buffer space */
  1168.  
  1169.     c_insert(len);
  1170.     while (len--)
  1171.     *Cursor++ = *s++;
  1172.     return 0;
  1173. }
  1174.  
  1175. void
  1176. DeleteBack(n)            /* delete the n characters before . */
  1177.     int     n;
  1178. {
  1179.     if (n <= 0)
  1180.     return;
  1181.     if (Cursor >= &InputBuf[n]) {
  1182.     c_delbefore(n);        /* delete before dot */
  1183.     Cursor -= n;
  1184.     if (Cursor < InputBuf)
  1185.         Cursor = InputBuf;    /* bounds check */
  1186.     }
  1187. }
  1188.  
  1189. CCRETVAL
  1190. e_digit(c)            /* gray magic here */
  1191.     register int c;
  1192. {
  1193.     if (!Isdigit(c))
  1194.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1195.  
  1196.     if (DoingArg) {        /* if doing an arg, add this in... */
  1197.     if (LastCmd == F_ARGFOUR)    /* if last command was ^U */
  1198.         Argument = c - '0';
  1199.     else {
  1200.         if (Argument > 1000000)
  1201.         return CC_ERROR;
  1202.         Argument = (Argument * 10) + (c - '0');
  1203.     }
  1204.     return(CC_ARGHACK);
  1205.     }
  1206.     else {
  1207.     if (LastChar + 1 >= InputLim)
  1208.         return CC_ERROR;    /* end of buffer space */
  1209.  
  1210.     if (inputmode != MODE_INSERT) {
  1211.         UndoBuf[UndoSize++] = *Cursor;
  1212.         UndoBuf[UndoSize] = '\0';
  1213.         c_delafter(1);   /* Do NOT use the saving ONE */
  1214.         }
  1215.     c_insert(1);
  1216.     *Cursor++ = c;
  1217.     DoingArg = 0;        /* just in case */
  1218.     RefPlusOne();        /* fast refresh for one char. */
  1219.     }
  1220.     return(CC_NORM);
  1221. }
  1222.  
  1223. CCRETVAL
  1224. e_argdigit(c)            /* for ESC-n */
  1225.     register int c;
  1226. {
  1227.     c &= ASCII;
  1228.  
  1229.     if (!Isdigit(c))
  1230.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1231.  
  1232.     if (DoingArg) {        /* if doing an arg, add this in... */
  1233.     if (Argument > 1000000)
  1234.         return CC_ERROR;
  1235.     Argument = (Argument * 10) + (c - '0');
  1236.     }
  1237.     else {            /* else starting an argument */
  1238.     Argument = c - '0';
  1239.     DoingArg = 1;
  1240.     }
  1241.     return(CC_ARGHACK);
  1242. }
  1243.  
  1244. CCRETVAL
  1245. v_zero(c)            /* command mode 0 for vi */
  1246.     register int c;
  1247. {
  1248.     if (DoingArg) {        /* if doing an arg, add this in... */
  1249.     if (Argument > 1000000)
  1250.         return CC_ERROR;
  1251.     Argument = (Argument * 10) + (c - '0');
  1252.     return(CC_ARGHACK);
  1253.     }
  1254.     else {            /* else starting an argument */
  1255.     Cursor = InputBuf;
  1256.     if (ActionFlag & DELETE) {
  1257.        c_delfini();
  1258.        return(CC_REFRESH);
  1259.         }
  1260.     RefCursor();        /* move the cursor */
  1261.     return(CC_NORM);
  1262.     }
  1263. }
  1264.  
  1265. /*ARGSUSED*/
  1266. CCRETVAL
  1267. e_newline(c)
  1268.     int c;
  1269. {                /* always ignore argument */
  1270.     PastBottom();
  1271.     *LastChar++ = '\n';        /* for the benefit of CSH */
  1272.     *LastChar = '\0';        /* just in case */
  1273.     if (VImode)
  1274.     InsertPos = InputBuf;    /* Reset editing position */
  1275.     return(CC_NEWLINE);    /* we must do a ResetInLine later */
  1276. }
  1277.  
  1278. /*ARGSUSED*/
  1279. CCRETVAL
  1280. e_send_eof(c)
  1281.     int c;
  1282. {                /* for when ^D is ONLY send-eof */
  1283.     PastBottom();
  1284.     *LastChar = '\0';        /* just in case */
  1285. #ifdef notdef
  1286.     ResetInLine();        /* reset the input pointers */
  1287. #endif
  1288.     return(CC_EOF);
  1289. }
  1290.  
  1291. /*ARGSUSED*/
  1292. CCRETVAL
  1293. e_complete(c)
  1294.     int c;
  1295. {
  1296.     *LastChar = '\0';        /* just in case */
  1297.     return(CC_COMPLETE);
  1298. }
  1299.  
  1300. /*ARGSUSED*/
  1301. CCRETVAL
  1302. v_cm_complete(c)
  1303.     int c;
  1304. {
  1305.     if (Cursor < LastChar)
  1306.     Cursor++;
  1307.     *LastChar = '\0';        /* just in case */
  1308.     return(CC_COMPLETE);
  1309. }
  1310.  
  1311. /*ARGSUSED*/
  1312. CCRETVAL
  1313. e_toggle_hist(c)
  1314.     int c;
  1315. {
  1316.     struct Hist *hp;
  1317.     int     h;
  1318.  
  1319.     *LastChar = '\0';        /* just in case */
  1320.  
  1321.     if (Hist_num <= 0) {
  1322.     return CC_ERROR;
  1323.     }
  1324.  
  1325.     hp = Histlist.Hnext;
  1326.     if (hp == NULL) {    /* this is only if no history */
  1327.     return(CC_ERROR);
  1328.     }
  1329.  
  1330.     for (h = 1; h < Hist_num; h++)
  1331.     hp = hp->Hnext;
  1332.  
  1333.     if (!CurrentHistLit) {
  1334.     if (hp->histline) {
  1335.         copyn(InputBuf, hp->histline, INBUFSIZE);
  1336.         CurrentHistLit = 1;
  1337.     }
  1338.     else {
  1339.         return CC_ERROR;
  1340.     }
  1341.     }
  1342.     else {
  1343.     (void) sprlex(InputBuf, &hp->Hlex);
  1344.     CurrentHistLit = 0;
  1345.     }
  1346.  
  1347.     LastChar = InputBuf + Strlen(InputBuf);
  1348.     if (LastChar > InputBuf) {
  1349.     if (LastChar[-1] == '\n')
  1350.         LastChar--;
  1351.     if (LastChar[-1] == ' ')
  1352.         LastChar--;
  1353.     if (LastChar < InputBuf)
  1354.         LastChar = InputBuf;
  1355.     }
  1356.  
  1357. #ifdef KSHVI
  1358.     if (VImode)
  1359.     Cursor = InputBuf;
  1360.     else
  1361. #endif /* KSHVI */
  1362.     Cursor = LastChar;
  1363.  
  1364.     return(CC_REFRESH);
  1365. }
  1366.  
  1367. /*ARGSUSED*/
  1368. CCRETVAL
  1369. e_up_hist(c)
  1370.     int c;
  1371. {
  1372.     Char    beep = 0;
  1373.  
  1374.     UndoAction = NOP;
  1375.     *LastChar = '\0';        /* just in case */
  1376.  
  1377.     if (Hist_num == 0) {    /* save the current buffer away */
  1378.     copyn(HistBuf, InputBuf, INBUFSIZE);
  1379.     LastHist = HistBuf + (LastChar - InputBuf);
  1380.     }
  1381.  
  1382.     Hist_num += Argument;
  1383.  
  1384.     if (c_get_histline() == CC_ERROR) {
  1385.     beep = 1;
  1386.     (void) c_get_histline(); /* Hist_num was fixed by first call */
  1387.     }
  1388.  
  1389.     Refresh();
  1390.     if (beep)
  1391.     return(CC_ERROR);
  1392.     else
  1393.     return(CC_NORM);    /* was CC_UP_HIST */
  1394. }
  1395.  
  1396. /*ARGSUSED*/
  1397. CCRETVAL
  1398. e_down_hist(c)
  1399.     int c;
  1400. {
  1401.     UndoAction = NOP;
  1402.     *LastChar = '\0';        /* just in case */
  1403.  
  1404.     Hist_num -= Argument;
  1405.  
  1406.     if (Hist_num < 0) {
  1407.     Hist_num = 0;
  1408.     return(CC_ERROR);    /* make it beep */
  1409.     }
  1410.  
  1411.     return(c_get_histline());
  1412. }
  1413.  
  1414.  
  1415.  
  1416. /*
  1417.  * c_hmatch() return True if the pattern matches the prefix
  1418.  */
  1419. static int
  1420. c_hmatch(str)
  1421. Char *str;
  1422. {
  1423.     if (Strncmp(patbuf, str, patlen) == 0)
  1424.     return 1;
  1425.     return Gmatch(str, patbuf);
  1426. }
  1427.  
  1428. /*
  1429.  * c_hsetpat(): Set the history seatch pattern
  1430.  */
  1431. static void
  1432. c_hsetpat()
  1433. {
  1434.     if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
  1435.     patlen = Cursor - InputBuf;
  1436.     if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
  1437.     if (patlen >= 0)  {
  1438.         (void) Strncpy(patbuf, InputBuf, patlen);
  1439.         patbuf[patlen] = '\0';
  1440.     }
  1441.     else
  1442.         patlen = Strlen(patbuf);
  1443.     }
  1444. #ifdef SDEBUG
  1445.     xprintf("\nHist_num = %d\n", Hist_num);
  1446.     xprintf("patlen = %d\n", patlen);
  1447.     xprintf("patbuf = \"%s\"\n", short2str(patbuf));
  1448.     xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
  1449. #endif
  1450. }
  1451.  
  1452. /*ARGSUSED*/
  1453. CCRETVAL
  1454. e_up_search_hist(c)
  1455.     int c;
  1456. {
  1457.     struct Hist *hp;
  1458.     int h;
  1459.     bool    found = 0;
  1460.  
  1461.     ActionFlag = NOP;
  1462.     UndoAction = NOP;
  1463.     *LastChar = '\0';        /* just in case */
  1464.     if (Hist_num < 0) {
  1465. #ifdef DEBUG_EDIT
  1466.     xprintf("tcsh: e_up_search_hist(): Hist_num < 0; resetting.\n");
  1467. #endif
  1468.     Hist_num = 0;
  1469.     return(CC_ERROR);
  1470.     }
  1471.  
  1472.     if (Hist_num == 0)
  1473.     {
  1474.     copyn(HistBuf, InputBuf, INBUFSIZE);
  1475.     LastHist = HistBuf + (LastChar - InputBuf);
  1476.     }
  1477.  
  1478.  
  1479.     hp = Histlist.Hnext;
  1480.     if (hp == NULL)
  1481.     return(CC_ERROR);
  1482.  
  1483.     c_hsetpat();        /* Set search pattern !! */
  1484.  
  1485.     for (h = 1; h <= Hist_num; h++)
  1486.     hp = hp->Hnext;
  1487.  
  1488.     while (hp != NULL) {
  1489.     if (hp->histline == NULL) {
  1490.         Char sbuf[BUFSIZE];
  1491.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  1492.     }
  1493. #ifdef SDEBUG
  1494.     xprintf("Comparing with \"%s\"\n", short2str(hp->histline));
  1495. #endif
  1496.     if ((Strncmp(hp->histline, InputBuf, LastChar-InputBuf) || hp->histline[LastChar-InputBuf]) && c_hmatch(hp->histline)) {
  1497.         found++;
  1498.         break;
  1499.     }
  1500.     h++;
  1501.     hp = hp->Hnext;
  1502.     }
  1503.  
  1504.     if (!found) {
  1505. #ifdef SDEBUG
  1506.     xprintf("not found\n"); 
  1507. #endif
  1508.     return(CC_ERROR);
  1509.     }
  1510.  
  1511.     Hist_num = h;
  1512.  
  1513.     return(c_get_histline());
  1514. }
  1515.  
  1516. /*ARGSUSED*/
  1517. CCRETVAL
  1518. e_down_search_hist(c)
  1519.     int c;
  1520. {
  1521.     struct Hist *hp;
  1522.     int h;
  1523.     bool    found = 0;
  1524.  
  1525.     ActionFlag = NOP;
  1526.     UndoAction = NOP;
  1527.     *LastChar = '\0';        /* just in case */
  1528.  
  1529.     if (Hist_num == 0)
  1530.     return(CC_ERROR);
  1531.  
  1532.     hp = Histlist.Hnext;
  1533.     if (hp == 0)
  1534.     return(CC_ERROR);
  1535.  
  1536.     c_hsetpat();        /* Set search pattern !! */
  1537.  
  1538.     for (h = 1; h < Hist_num && hp; h++) {
  1539.     if (hp->histline == NULL) {
  1540.         Char sbuf[BUFSIZE];
  1541.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  1542.     }
  1543. #ifdef SDEBUG
  1544.     xprintf("Comparing with \"%s\"\n", short2str(hp->histline));
  1545. #endif
  1546.     if ((Strncmp(hp->histline, InputBuf, LastChar-InputBuf) || hp->histline[LastChar-InputBuf]) && c_hmatch(hp->histline))
  1547.         found = h;
  1548.     hp = hp->Hnext;
  1549.     }
  1550.  
  1551.     if (!found) {        /* is it the current history number? */
  1552.     if (!c_hmatch(HistBuf)) {
  1553. #ifdef SDEBUG
  1554.         xprintf("not found\n"); 
  1555. #endif
  1556.         return(CC_ERROR);
  1557.     }
  1558.     }
  1559.  
  1560.     Hist_num = found;
  1561.  
  1562.     return(c_get_histline());
  1563. }
  1564.  
  1565. /*ARGSUSED*/
  1566. CCRETVAL
  1567. e_helpme(c)
  1568.     int c;
  1569. {
  1570.     PastBottom();
  1571.     *LastChar = '\0';        /* just in case */
  1572.     return(CC_HELPME);
  1573. }
  1574.  
  1575. /*ARGSUSED*/
  1576. CCRETVAL
  1577. e_correct(c)
  1578.     int c;
  1579. {
  1580.     *LastChar = '\0';        /* just in case */
  1581.     return(CC_CORRECT);
  1582. }
  1583.  
  1584. /*ARGSUSED*/
  1585. CCRETVAL
  1586. e_correctl(c)
  1587.     int c;
  1588. {
  1589.     *LastChar = '\0';        /* just in case */
  1590.     return(CC_CORRECT_L);
  1591. }
  1592.  
  1593. /*ARGSUSED*/
  1594. CCRETVAL
  1595. e_run_fg_editor(c)
  1596.     int c;
  1597. {
  1598.     register struct process *pp;
  1599.     extern bool tellwhat;
  1600.  
  1601.     if ((pp = find_stop_ed()) != NULL) {
  1602.     /* save our editor state so we can restore it */
  1603.     tellwhat = 1;
  1604.     copyn(WhichBuf, InputBuf, INBUFSIZE);
  1605.     LastWhich = WhichBuf + (LastChar - InputBuf);
  1606.     CursWhich = WhichBuf + (Cursor - InputBuf);
  1607.     HistWhich = Hist_num;
  1608.     Hist_num = 0;        /* for the history commands */
  1609.  
  1610.     /* put the tty in a sane mode */
  1611.     PastBottom();
  1612.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  1613.  
  1614.     /* do it! */
  1615.     fg_proc_entry(pp);
  1616.  
  1617.     (void) Rawmode();    /* go on */
  1618.     Refresh();
  1619.     tellwhat = 0;
  1620.     }
  1621.     return(CC_NORM);
  1622. }
  1623.  
  1624. /*ARGSUSED*/
  1625. CCRETVAL
  1626. e_list_choices(c)
  1627.     int c;
  1628. {
  1629.     PastBottom();
  1630.     *LastChar = '\0';        /* just in case */
  1631.     return(CC_LIST_CHOICES);
  1632. }
  1633.  
  1634. /*ARGSUSED*/
  1635. CCRETVAL
  1636. e_list_glob(c)
  1637.     int c;
  1638. {
  1639.     PastBottom();
  1640.     *LastChar = '\0';        /* just in case */
  1641.     return(CC_LIST_GLOB);
  1642. }
  1643.  
  1644. /*ARGSUSED*/
  1645. CCRETVAL
  1646. e_expand_glob(c)
  1647.     int c;
  1648. {
  1649.     *LastChar = '\0';        /* just in case */
  1650.     return(CC_EXPAND_GLOB);
  1651. }
  1652.  
  1653. /*ARGSUSED*/
  1654. CCRETVAL
  1655. e_normalize_path(c)
  1656.     int c;
  1657. {
  1658.     *LastChar = '\0';        /* just in case */
  1659.     return(CC_NORMALIZE_PATH);
  1660. }
  1661. /*ARGSUSED*/
  1662. CCRETVAL
  1663. e_expand_vars(c)
  1664.     int c;
  1665. {
  1666.     *LastChar = '\0';        /* just in case */
  1667.     return(CC_EXPAND_VARS);
  1668. }
  1669.  
  1670. /*ARGSUSED*/
  1671. CCRETVAL
  1672. e_which(c)
  1673.     int c;
  1674. {                /* do a fast command line which(1) */
  1675.     PastBottom();
  1676.     *LastChar = '\0';        /* just in case */
  1677.     return(CC_WHICH);
  1678. }
  1679.  
  1680. /*ARGSUSED*/
  1681. CCRETVAL
  1682. e_last_item(c)
  1683.     int c;
  1684. {                /* insert the last element of the prev. cmd */
  1685.     register Char *cp;
  1686.     register struct Hist *hp;
  1687.     register struct wordent *wp, *firstp;
  1688.     register int i;
  1689.  
  1690.     if (Argument <= 0)
  1691.     return(CC_ERROR);
  1692.  
  1693.     hp = Histlist.Hnext;
  1694.     if (hp == NULL) {    /* this is only if no history */
  1695.     return(CC_ERROR);
  1696.     }
  1697.  
  1698.     wp = (hp->Hlex).prev;
  1699.  
  1700.     if (wp->prev == (struct wordent *) NULL)
  1701.     return(CC_ERROR);    /* an empty history entry */
  1702.  
  1703.     firstp = (hp->Hlex).next;
  1704.  
  1705.     for (i = 0; i < Argument; i++) {    /* back up arg words in lex */
  1706.     wp = wp->prev;
  1707.     if (wp == firstp)
  1708.         break;
  1709.     }
  1710.  
  1711.     while (i > 0) {
  1712.     cp = wp->word;
  1713.  
  1714.     if (!cp)
  1715.         return(CC_ERROR);
  1716.  
  1717.     if (InsertStr(cp))
  1718.         return(CC_ERROR);
  1719.  
  1720.     wp = wp->next;
  1721.     i--;
  1722.     }
  1723.  
  1724.     return(CC_REFRESH);
  1725. }
  1726.  
  1727. /*ARGSUSED*/
  1728. CCRETVAL
  1729. e_yank_kill(c)
  1730.     int c;
  1731. {                /* almost like GnuEmacs */
  1732.     register Char *kp, *cp;
  1733.  
  1734.     if (LastKill == KillBuf)    /* if zero content */
  1735.     return(CC_ERROR);
  1736.  
  1737.     if (LastChar + (LastKill - KillBuf) >= InputLim)
  1738.     return(CC_ERROR);    /* end of buffer space */
  1739.  
  1740.     /* else */
  1741.     Mark = Cursor;        /* set the mark */
  1742.     cp = Cursor;        /* for speed */
  1743.  
  1744.     c_insert(LastKill - KillBuf);    /* open the space, */
  1745.     for (kp = KillBuf; kp < LastKill; kp++)    /* copy the chars */
  1746.     *cp++ = *kp;
  1747.  
  1748.     if (Argument == 1)        /* if an arg, cursor at beginning */
  1749.     Cursor = cp;        /* else cursor at end */
  1750.  
  1751.     return(CC_REFRESH);
  1752. }
  1753.  
  1754. /*ARGSUSED*/
  1755. CCRETVAL
  1756. v_delprev(c)         /* Backspace key in insert mode */
  1757.     int c;
  1758. {
  1759.     int rc;
  1760.  
  1761.     rc = CC_ERROR;
  1762.  
  1763.     if (InsertPos != 0) {
  1764.     if (InsertPos <= Cursor - Argument) {
  1765.         c_delbefore(Argument);    /* delete before */
  1766.         Cursor -= Argument;
  1767.         rc = CC_REFRESH;
  1768.     }
  1769.     }
  1770.     return(rc);
  1771. }   /* v_delprev  */
  1772.  
  1773. /*ARGSUSED*/
  1774. CCRETVAL
  1775. e_delprev(c)
  1776.     int c;
  1777. {
  1778.     if (Cursor > InputBuf) {
  1779.     c_delbefore(Argument);    /* delete before dot */
  1780.     Cursor -= Argument;
  1781.     if (Cursor < InputBuf)
  1782.         Cursor = InputBuf;    /* bounds check */
  1783.     return(CC_REFRESH);
  1784.     }
  1785.     else {
  1786.     return(CC_ERROR);
  1787.     }
  1788. }
  1789.  
  1790. /*ARGSUSED*/
  1791. CCRETVAL
  1792. e_delwordprev(c)
  1793.     int c;
  1794. {
  1795.     register Char *cp, *p, *kp;
  1796.  
  1797.     if (Cursor == InputBuf)
  1798.     return(CC_ERROR);
  1799.     /* else */
  1800.  
  1801.     cp = c_prev_word(Cursor, InputBuf, Argument);
  1802.  
  1803.     for (p = cp, kp = KillBuf; p < Cursor; p++)    /* save the text */
  1804.     *kp++ = *p;
  1805.     LastKill = kp;
  1806.  
  1807.     c_delbefore(Cursor - cp);    /* delete before dot */
  1808.     Cursor = cp;
  1809.     if (Cursor < InputBuf)
  1810.     Cursor = InputBuf;    /* bounds check */
  1811.     return(CC_REFRESH);
  1812. }
  1813.  
  1814. /*ARGSUSED*/
  1815. CCRETVAL
  1816. e_delnext(c)
  1817.     int c;
  1818. {
  1819.     if (Cursor == LastChar) {/* if I'm at the end */
  1820.     if (!VImode) {
  1821.         if (Cursor == InputBuf) {    
  1822.         /* if I'm also at the beginning */
  1823.         so_write(STReof, 4);/* then do a EOF */
  1824.         flush();
  1825.         return(CC_EOF);
  1826.         }
  1827.         else 
  1828.         return(CC_ERROR);
  1829.     }
  1830.     else {
  1831.         if (Cursor != InputBuf)
  1832.         Cursor--;
  1833.         else
  1834.         return(CC_ERROR);
  1835.     }
  1836.     }
  1837.     c_delafter(Argument);    /* delete after dot */
  1838.     if (Cursor > LastChar)
  1839.     Cursor = LastChar;    /* bounds check */
  1840.     return(CC_REFRESH);
  1841. }
  1842.  
  1843. /*ARGSUSED*/
  1844. CCRETVAL
  1845. e_list_delnext(c)
  1846.     int c;
  1847. {
  1848.     if (Cursor == LastChar) {    /* if I'm at the end */
  1849.     if (Cursor == InputBuf) {    /* if I'm also at the beginning */
  1850.         so_write(STReof, 4);/* then do a EOF */
  1851.         flush();
  1852.         return(CC_EOF);
  1853.     }
  1854.     else {
  1855.         PastBottom();
  1856.         *LastChar = '\0';    /* just in case */
  1857.         return(CC_LIST_CHOICES);
  1858.     }
  1859.     }
  1860.     else {
  1861.     c_delafter(Argument);    /* delete after dot */
  1862.     if (Cursor > LastChar)
  1863.         Cursor = LastChar;    /* bounds check */
  1864.     return(CC_REFRESH);
  1865.     }
  1866. }
  1867.  
  1868. /*ARGSUSED*/
  1869. CCRETVAL
  1870. e_list_eof(c)
  1871.     int c;
  1872. {
  1873.     if (Cursor == LastChar && Cursor == InputBuf) {
  1874.     so_write(STReof, 4);    /* then do a EOF */
  1875.     flush();
  1876.     return(CC_EOF);
  1877.     }
  1878.     else {
  1879.     PastBottom();
  1880.     *LastChar = '\0';    /* just in case */
  1881.     return(CC_LIST_CHOICES);
  1882.     }
  1883. }
  1884.  
  1885. /*ARGSUSED*/
  1886. CCRETVAL
  1887. e_delwordnext(c)
  1888.     int c;
  1889. {
  1890.     register Char *cp, *p, *kp;
  1891.  
  1892.     if (Cursor == LastChar)
  1893.     return(CC_ERROR);
  1894.     /* else */
  1895.  
  1896.     cp = c_next_word(Cursor, LastChar, Argument);
  1897.  
  1898.     for (p = Cursor, kp = KillBuf; p < cp; p++)    /* save the text */
  1899.     *kp++ = *p;
  1900.     LastKill = kp;
  1901.  
  1902.     c_delafter(cp - Cursor);    /* delete after dot */
  1903.     if (Cursor > LastChar)
  1904.     Cursor = LastChar;    /* bounds check */
  1905.     return(CC_REFRESH);
  1906. }
  1907.  
  1908. /*ARGSUSED*/
  1909. CCRETVAL
  1910. e_toend(c)
  1911.     int c;
  1912. {
  1913.     Cursor = LastChar;
  1914.     if (VImode)
  1915.     if (ActionFlag & DELETE) {
  1916.         c_delfini();
  1917.         return(CC_REFRESH);
  1918.     }
  1919.     RefCursor();        /* move the cursor */
  1920.     return(CC_NORM);
  1921. }
  1922.  
  1923. /*ARGSUSED*/
  1924. CCRETVAL
  1925. e_tobeg(c)
  1926.     int c;
  1927. {
  1928.     Cursor = InputBuf;
  1929.  
  1930.     if (VImode) {
  1931.        while (Isspace(*Cursor)) /* We want FIRST non space character */
  1932.     Cursor++;
  1933.     if (ActionFlag & DELETE) {
  1934.         c_delfini();
  1935.         return(CC_REFRESH);
  1936.     }
  1937.     }
  1938.  
  1939.     RefCursor();        /* move the cursor */
  1940.     return(CC_NORM);
  1941. }
  1942.  
  1943. /*ARGSUSED*/
  1944. CCRETVAL
  1945. e_killend(c)
  1946.     int c;
  1947. {
  1948.     register Char *kp, *cp;
  1949.  
  1950.     cp = Cursor;
  1951.     kp = KillBuf;
  1952.     while (cp < LastChar)
  1953.     *kp++ = *cp++;        /* copy it */
  1954.     LastKill = kp;
  1955.     LastChar = Cursor;        /* zap! -- delete to end */
  1956.     return(CC_REFRESH);
  1957. }
  1958.  
  1959.  
  1960. /*ARGSUSED*/
  1961. CCRETVAL
  1962. e_killbeg(c)
  1963.     int c;
  1964. {
  1965.     register Char *kp, *cp;
  1966.  
  1967.     cp = InputBuf;
  1968.     kp = KillBuf;
  1969.     while (cp < Cursor)
  1970.     *kp++ = *cp++;        /* copy it */
  1971.     LastKill = kp;
  1972.     c_delbefore(Cursor - InputBuf);
  1973.     Cursor = InputBuf;        /* zap! */
  1974.     return(CC_REFRESH);
  1975. }
  1976.  
  1977. /*ARGSUSED*/
  1978. CCRETVAL
  1979. e_killall(c)
  1980.     int c;
  1981. {
  1982.     register Char *kp, *cp;
  1983.  
  1984.     cp = InputBuf;
  1985.     kp = KillBuf;
  1986.     while (cp < LastChar)
  1987.     *kp++ = *cp++;        /* copy it */
  1988.     LastKill = kp;
  1989.     LastChar = InputBuf;    /* zap! -- delete all of it */
  1990.     Cursor = InputBuf;
  1991.     return(CC_REFRESH);
  1992. }
  1993.  
  1994. /*ARGSUSED*/
  1995. CCRETVAL
  1996. e_killregion(c)
  1997.     int c;
  1998. {
  1999.     register Char *kp, *cp;
  2000.  
  2001.     if (!Mark)
  2002.     return(CC_ERROR);
  2003.  
  2004.     if (Mark > Cursor) {
  2005.     cp = Cursor;
  2006.     kp = KillBuf;
  2007.     while (cp < Mark)
  2008.         *kp++ = *cp++;    /* copy it */
  2009.     LastKill = kp;
  2010.     c_delafter(cp - Cursor);/* delete it - UNUSED BY VI mode */
  2011.     }
  2012.     else {            /* mark is before cursor */
  2013.     cp = Mark;
  2014.     kp = KillBuf;
  2015.     while (cp < Cursor)
  2016.         *kp++ = *cp++;    /* copy it */
  2017.     LastKill = kp;
  2018.     c_delbefore(cp - Mark);
  2019.     Cursor = Mark;
  2020.     }
  2021.     return(CC_REFRESH);
  2022. }
  2023.  
  2024. /*ARGSUSED*/
  2025. CCRETVAL
  2026. e_copyregion(c)
  2027.     int c;
  2028. {
  2029.     register Char *kp, *cp;
  2030.  
  2031.     if (!Mark)
  2032.     return(CC_ERROR);
  2033.  
  2034.     if (Mark > Cursor) {
  2035.     cp = Cursor;
  2036.     kp = KillBuf;
  2037.     while (cp < Mark)
  2038.         *kp++ = *cp++;    /* copy it */
  2039.     LastKill = kp;
  2040.     }
  2041.     else {            /* mark is before cursor */
  2042.     cp = Mark;
  2043.     kp = KillBuf;
  2044.     while (cp < Cursor)
  2045.         *kp++ = *cp++;    /* copy it */
  2046.     LastKill = kp;
  2047.     }
  2048.     return(CC_NORM);        /* don't even need to Refresh() */
  2049. }
  2050.  
  2051. /*ARGSUSED*/
  2052. CCRETVAL
  2053. e_charswitch(cc)
  2054.     int cc;
  2055. {
  2056.     register Char c;
  2057.  
  2058.     if (Cursor < LastChar) {
  2059.     if (LastChar <= &InputBuf[1]) {
  2060.         return(CC_ERROR);
  2061.     }
  2062.     else {
  2063.         Cursor++;
  2064.     }
  2065.     }
  2066.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  2067.     c = Cursor[-2];
  2068.     Cursor[-2] = Cursor[-1];
  2069.     Cursor[-1] = c;
  2070.     return(CC_REFRESH);
  2071.     }
  2072.     else {
  2073.     return(CC_ERROR);
  2074.     }
  2075. }
  2076.  
  2077. /*ARGSUSED*/
  2078. CCRETVAL
  2079. e_gcharswitch(cc)
  2080.     int cc;
  2081. {                /* gosmacs style ^T */
  2082.     register Char c;
  2083.  
  2084.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  2085.     c = Cursor[-2];
  2086.     Cursor[-2] = Cursor[-1];
  2087.     Cursor[-1] = c;
  2088.     return(CC_REFRESH);
  2089.     }
  2090.     else {
  2091.     return(CC_ERROR);
  2092.     }
  2093. }
  2094.  
  2095. /*ARGSUSED*/
  2096. CCRETVAL
  2097. e_charback(c)
  2098.     int c;
  2099. {
  2100.     if (Cursor > InputBuf) {
  2101.     Cursor -= Argument;
  2102.     if (Cursor < InputBuf)
  2103.         Cursor = InputBuf;
  2104.  
  2105.     if (VImode)
  2106.         if (ActionFlag & DELETE) {
  2107.         c_delfini();
  2108.         return(CC_REFRESH);
  2109.         }
  2110.  
  2111.     RefCursor();
  2112.     return(CC_NORM);
  2113.     }
  2114.     else {
  2115.     return(CC_ERROR);
  2116.     }
  2117. }
  2118.  
  2119. /*ARGSUSED*/
  2120. CCRETVAL
  2121. v_wordback(c)
  2122.     int c;
  2123. {
  2124.     if (Cursor == InputBuf)
  2125.     return(CC_ERROR);
  2126.     /* else */
  2127.  
  2128.     Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */
  2129.  
  2130.     if (ActionFlag & DELETE) {
  2131.     c_delfini();
  2132.     return(CC_REFRESH);
  2133.     }
  2134.  
  2135.     RefCursor();
  2136.     return(CC_NORM);
  2137. }
  2138.  
  2139. /*ARGSUSED*/
  2140. CCRETVAL
  2141. e_wordback(c)
  2142.     int c;
  2143. {
  2144.     if (Cursor == InputBuf)
  2145.     return(CC_ERROR);
  2146.     /* else */
  2147.  
  2148.     Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
  2149.  
  2150.     if (VImode) 
  2151.     if (ActionFlag & DELETE) {
  2152.         c_delfini();
  2153.         return(CC_REFRESH);
  2154.     }
  2155.  
  2156.     RefCursor();
  2157.     return(CC_NORM);
  2158. }
  2159.  
  2160. /*ARGSUSED*/
  2161. CCRETVAL
  2162. e_charfwd(c)
  2163.     int c;
  2164. {
  2165.     if (Cursor < LastChar) {
  2166.     Cursor += Argument;
  2167.     if (Cursor > LastChar)
  2168.         Cursor = LastChar;
  2169.  
  2170.     if (VImode)
  2171.         if (ActionFlag & DELETE) {
  2172.         c_delfini();
  2173.         return(CC_REFRESH);
  2174.         }
  2175.  
  2176.     RefCursor();
  2177.     return(CC_NORM);
  2178.     }
  2179.     else {
  2180.     return(CC_ERROR);
  2181.     }
  2182. }
  2183.  
  2184. /*ARGSUSED*/
  2185. CCRETVAL
  2186. e_wordfwd(c)
  2187.     int c;
  2188. {
  2189.     if (Cursor == LastChar)
  2190.     return(CC_ERROR);
  2191.     /* else */
  2192.  
  2193.     Cursor = c_next_word(Cursor, LastChar, Argument);
  2194.  
  2195.     if (VImode)
  2196.     if (ActionFlag & DELETE) {
  2197.         c_delfini();
  2198.         return(CC_REFRESH);
  2199.     }
  2200.  
  2201.     RefCursor();
  2202.     return(CC_NORM);
  2203. }
  2204.  
  2205. /*ARGSUSED*/
  2206. CCRETVAL
  2207. v_wordfwd(c)
  2208.     int c;
  2209. {
  2210.     if (Cursor == LastChar)
  2211.     return(CC_ERROR);
  2212.     /* else */
  2213.  
  2214.     Cursor = c_nexword(Cursor, LastChar, Argument);
  2215.  
  2216.     if (VImode)
  2217.     if (ActionFlag & DELETE) {
  2218.         c_delfini();
  2219.         return(CC_REFRESH);
  2220.     }
  2221.  
  2222.     RefCursor();
  2223.     return(CC_NORM);
  2224. }
  2225.  
  2226. /*ARGSUSED*/
  2227. CCRETVAL
  2228. v_wordbegnext(c)
  2229.     int c;
  2230. {
  2231.     if (Cursor == LastChar)
  2232.     return(CC_ERROR);
  2233.     /* else */
  2234.  
  2235.     Cursor = c_next_word(Cursor, LastChar, Argument);
  2236.     if (Cursor < LastChar)
  2237.     Cursor++;
  2238.  
  2239.     if (VImode)
  2240.     if (ActionFlag & DELETE) {
  2241.         c_delfini();
  2242.         return(CC_REFRESH);
  2243.     }
  2244.  
  2245.     RefCursor();
  2246.     return(CC_NORM);
  2247. }
  2248.  
  2249. /*ARGSUSED*/
  2250. static CCRETVAL
  2251. v_repeat_srch(c)
  2252.     int c;
  2253. {
  2254. #ifdef SDEBUG
  2255.     xprintf("dir %d patlen %d patbuf %s\n", 
  2256.         c, patlen, short2str(patbuf));
  2257. #endif
  2258.  
  2259.     LastCmd = c;  /* Hack to stop c_hsetpat */
  2260.     LastChar = InputBuf;
  2261.     switch (c) {
  2262.     case F_DOWN_SEARCH_HIST:
  2263.     return(e_down_search_hist(0));
  2264.     case F_UP_SEARCH_HIST:
  2265.     return(e_up_search_hist(0));
  2266.     default:
  2267.     return(CC_ERROR);
  2268.     }
  2269. }
  2270.  
  2271. static CCRETVAL
  2272. v_csearch_back(ch, count, tflag)
  2273.     int ch, count, tflag;
  2274. {
  2275.     Char *cp;
  2276.  
  2277.     cp = Cursor;
  2278.     while (count--) {
  2279.     if (*cp == ch) 
  2280.         cp--;
  2281.     while (cp > InputBuf && *cp != ch) 
  2282.         cp--;
  2283.     }
  2284.  
  2285.     if (cp < InputBuf || (cp == InputBuf && *cp != ch))
  2286.     return(CC_ERROR);
  2287.  
  2288.     if (*cp == ch && tflag)
  2289.     cp++;
  2290.  
  2291.     Cursor = cp;
  2292.  
  2293.     if (ActionFlag & DELETE) {
  2294.     Cursor++;
  2295.     c_delfini();
  2296.     return(CC_REFRESH);
  2297.     }
  2298.  
  2299.     RefCursor();
  2300.     return(CC_NORM);
  2301. }
  2302.  
  2303. static CCRETVAL
  2304. v_csearch_fwd(ch, count, tflag)
  2305.     int ch, count, tflag;
  2306. {
  2307.     Char *cp;
  2308.  
  2309.     cp = Cursor;
  2310.     while (count--) {
  2311.     if(*cp == ch) 
  2312.         cp++;
  2313.     while (cp < LastChar && *cp != ch) 
  2314.         cp++;
  2315.     }
  2316.  
  2317.     if (cp >= LastChar)
  2318.     return(CC_ERROR);
  2319.  
  2320.     if (*cp == ch && tflag)
  2321.     cp--;
  2322.  
  2323.     Cursor = cp;
  2324.  
  2325.     if (ActionFlag & DELETE) {
  2326.     Cursor++;
  2327.     c_delfini();
  2328.     return(CC_REFRESH);
  2329.     }
  2330.     RefCursor();
  2331.     return(CC_NORM);
  2332. }
  2333.  
  2334. /*ARGSUSED*/
  2335. static CCRETVAL
  2336. v_action(c)
  2337.     int c;
  2338. {
  2339.     register Char *cp, *kp;
  2340.  
  2341.     if (ActionFlag == DELETE) {
  2342.     ActionFlag = NOP;
  2343.     ActionPos = 0;
  2344.     
  2345.     UndoSize = 0;
  2346.     kp = UndoBuf;
  2347.     for (cp = InputBuf; cp < LastChar; cp++) {
  2348.         *kp++ = *cp;
  2349.         UndoSize++;
  2350.     }
  2351.         
  2352.     UndoAction = INSERT;
  2353.     UndoPtr  = InputBuf;
  2354.     LastChar = InputBuf;
  2355.     Cursor   = InputBuf;
  2356.     if (c & INSERT)
  2357.         c_alternativ_key_map(0);
  2358.         
  2359.     return(CC_REFRESH);
  2360.     }
  2361. #ifdef notdef
  2362.     else if (ActionFlag == NOP) {
  2363. #endif
  2364.     ActionPos = Cursor;
  2365.     ActionFlag = c;
  2366.     return(CC_ARGHACK);  /* Do NOT clear out argument */
  2367. #ifdef notdef
  2368.     }
  2369.     else {
  2370.     ActionFlag = 0;
  2371.     ActionPos = 0;
  2372.     return(CC_ERROR);
  2373.     }
  2374. #endif
  2375. }
  2376. #ifdef COMMENT
  2377. /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
  2378. static void
  2379. c_get_word(begin, end)
  2380.     Char  **begin;
  2381.     Char  **end;
  2382. {
  2383.     Char   *cp;
  2384.  
  2385.     cp = &Cursor[0];
  2386.     while (Argument--) {
  2387.     while ((cp <= LastChar) && (isword(*cp)))
  2388.         cp++;
  2389.     *end = --cp;
  2390.     while ((cp >= InputBuf) && (isword(*cp)))
  2391.         cp--;
  2392.     *begin = ++cp;
  2393.     }
  2394. }
  2395. #endif                /* COMMENT */
  2396.  
  2397. /*ARGSUSED*/
  2398. CCRETVAL
  2399. e_uppercase(c)
  2400.     int c;
  2401. {
  2402.     Char   *cp, *end;
  2403.  
  2404.     end = c_next_word(Cursor, LastChar, Argument);
  2405.  
  2406.     for (cp = Cursor; cp < end; cp++)    /* PWP: was cp=begin */
  2407.     if (Islower(*cp))
  2408.         *cp = Toupper(*cp);
  2409.  
  2410.     Cursor = end;
  2411.     if (Cursor > LastChar)
  2412.     Cursor = LastChar;
  2413.     return(CC_REFRESH);
  2414. }
  2415.  
  2416.  
  2417. /*ARGSUSED*/
  2418. CCRETVAL
  2419. e_capitolcase(c)
  2420.     int c;
  2421. {
  2422.     Char   *cp, *end;
  2423.  
  2424.     end = c_next_word(Cursor, LastChar, Argument);
  2425.  
  2426.     cp = Cursor;
  2427.     for (; cp < end; cp++) {
  2428.     if (Isalpha(*cp)) {
  2429.         if (Islower(*cp))
  2430.         *cp = Toupper(*cp);
  2431.         cp++;
  2432.         break;
  2433.     }
  2434.     }
  2435.     for (; cp < end; cp++)
  2436.     if (Isupper(*cp))
  2437.         *cp = Tolower(*cp);
  2438.  
  2439.     Cursor = end;
  2440.     if (Cursor > LastChar)
  2441.     Cursor = LastChar;
  2442.     return(CC_REFRESH);
  2443. }
  2444.  
  2445. /*ARGSUSED*/
  2446. CCRETVAL
  2447. e_lowercase(c)
  2448.     int c;
  2449. {
  2450.     Char   *cp, *end;
  2451.  
  2452.     end = c_next_word(Cursor, LastChar, Argument);
  2453.  
  2454.     for (cp = Cursor; cp < end; cp++)
  2455.     if (Isupper(*cp))
  2456.         *cp = Tolower(*cp);
  2457.  
  2458.     Cursor = end;
  2459.     if (Cursor > LastChar)
  2460.     Cursor = LastChar;
  2461.     return(CC_REFRESH);
  2462. }
  2463.  
  2464.  
  2465. /*ARGSUSED*/
  2466. CCRETVAL
  2467. e_set_mark(c)
  2468.     int c;
  2469. {
  2470.     Mark = Cursor;
  2471.     return(CC_NORM);
  2472. }
  2473.  
  2474. /*ARGSUSED*/
  2475. CCRETVAL
  2476. e_exchange_mark(c)
  2477.     int c;
  2478. {
  2479.     register Char *cp;
  2480.  
  2481.     cp = Cursor;
  2482.     Cursor = Mark;
  2483.     Mark = cp;
  2484.     RefCursor();
  2485.     return(CC_NORM);
  2486. }
  2487.  
  2488. /*ARGSUSED*/
  2489. CCRETVAL
  2490. e_argfour(c)
  2491.     int c;
  2492. {                /* multiply current argument by 4 */
  2493.     if (Argument > 1000000)
  2494.     return CC_ERROR;
  2495.     DoingArg = 1;
  2496.     Argument *= 4;
  2497.     return(CC_ARGHACK);
  2498. }
  2499.  
  2500. /*ARGSUSED*/
  2501. CCRETVAL
  2502. e_quote(c)
  2503.     int c;
  2504. {
  2505.     Char    ch;
  2506.     int     num;
  2507.  
  2508.     QuoteModeOn();
  2509.     num = GetNextChar(&ch);
  2510.     QuoteModeOff();
  2511.     if (num == 1)
  2512.     return e_insert(ch);
  2513.     else
  2514.     return e_send_eof(0);
  2515. }
  2516.  
  2517. /*ARGSUSED*/
  2518. CCRETVAL
  2519. e_metanext(c)
  2520.     int c;
  2521. {
  2522.     MetaNext = 1;
  2523.     return(CC_ARGHACK);    /* preserve argument */
  2524. }
  2525.  
  2526. #ifdef notdef
  2527. /*ARGSUSED*/
  2528. CCRETVAL
  2529. e_extendnext(c)
  2530.     int c;
  2531. {
  2532.     CurrentKeyMap = CcAltMap;
  2533.     return(CC_ARGHACK);    /* preserve argument */
  2534. }
  2535.  
  2536. #endif
  2537.  
  2538. /*ARGSUSED*/
  2539. CCRETVAL
  2540. v_insbeg(c)
  2541.     int c;
  2542. {                /* move to beginning of line and start vi
  2543.                  * insert mode */
  2544.     Cursor = InputBuf;
  2545.     InsertPos = Cursor;
  2546.  
  2547.     UndoPtr  = Cursor;
  2548.     UndoAction = DELETE;
  2549.  
  2550.     RefCursor();        /* move the cursor */
  2551.     c_alternativ_key_map(0);
  2552.     return(CC_NORM);
  2553. }
  2554.  
  2555. /*ARGSUSED*/
  2556. CCRETVAL
  2557. v_replone(c)
  2558.     int c;
  2559. {                /* vi mode overwrite one character */
  2560.     c_alternativ_key_map(0);
  2561.     inputmode = MODE_REPLACE_1;
  2562.     UndoAction = CHANGE;    /* Set Up for VI undo command */
  2563.     UndoPtr = Cursor;
  2564.     UndoSize = 0;
  2565.     return(CC_NORM);
  2566. }
  2567.  
  2568. /*ARGSUSED*/
  2569. CCRETVAL
  2570. v_replmode(c)
  2571.     int c;
  2572. {                /* vi mode start overwriting */
  2573.     c_alternativ_key_map(0);
  2574.     inputmode = MODE_REPLACE;
  2575.     UndoAction = CHANGE;    /* Set Up for VI undo command */
  2576.     UndoPtr = Cursor;
  2577.     UndoSize = 0;
  2578.     return(CC_NORM);
  2579. }
  2580.  
  2581. /*ARGSUSED*/
  2582. CCRETVAL
  2583. v_substchar(c)
  2584.     int c;
  2585. {                /* vi mode substitute for one char */
  2586.     c_delafter(Argument);
  2587.     c_alternativ_key_map(0);
  2588.     return(CC_REFRESH);
  2589. }
  2590.  
  2591. /*ARGSUSED*/
  2592. CCRETVAL
  2593. v_substline(c)
  2594.     int c;
  2595. {                /* vi mode replace whole line */
  2596.     (void) e_killall(0);
  2597.     c_alternativ_key_map(0);
  2598.     return(CC_NORM);
  2599. }
  2600.  
  2601. /*ARGSUSED*/
  2602. CCRETVAL
  2603. v_chgtoend(c)
  2604.     int c;
  2605. {                /* vi mode change to end of line */
  2606.     (void) e_killend(0);
  2607.     c_alternativ_key_map(0);
  2608.     return(CC_REFRESH);
  2609. }
  2610.  
  2611. /*ARGSUSED*/
  2612. CCRETVAL
  2613. v_insert(c)
  2614.     int c;
  2615. {                /* vi mode start inserting */
  2616.     c_alternativ_key_map(0);
  2617.  
  2618.     InsertPos = Cursor;
  2619.     UndoPtr = Cursor;
  2620.     UndoAction = DELETE;
  2621.  
  2622.     return(CC_NORM);
  2623. }
  2624.  
  2625. /*ARGSUSED*/
  2626. CCRETVAL
  2627. v_add(c)
  2628.     int c;
  2629. {                /* vi mode start adding */
  2630.     c_alternativ_key_map(0);
  2631.     if (Cursor < LastChar)
  2632.     {
  2633.     Cursor++;
  2634.     if (Cursor > LastChar)
  2635.         Cursor = LastChar;
  2636.     RefCursor();
  2637.     }
  2638.  
  2639.     InsertPos = Cursor;
  2640.     UndoPtr = Cursor;
  2641.     UndoAction = DELETE;
  2642.  
  2643.     return(CC_NORM);
  2644. }
  2645.  
  2646. /*ARGSUSED*/
  2647. CCRETVAL
  2648. v_addend(c)
  2649.     int c;
  2650. {                /* vi mode to add at end of line */
  2651.     c_alternativ_key_map(0);
  2652.     Cursor = LastChar;
  2653.  
  2654.     InsertPos = LastChar;    /* Mark where insertion begins */
  2655.     UndoPtr = LastChar;
  2656.     UndoAction = DELETE;
  2657.  
  2658.     RefCursor();
  2659.     return(CC_NORM);
  2660. }
  2661.  
  2662. /*ARGSUSED*/
  2663. CCRETVAL
  2664. v_change_case(cc)
  2665.     int cc;
  2666. {
  2667.     char    c;
  2668.  
  2669.     if (Cursor < LastChar) {
  2670.     c = *Cursor;
  2671.     if (Isupper(c))
  2672.         *Cursor++ = Tolower(c);
  2673.     else if (Islower(c))
  2674.         *Cursor++ = Toupper(c);
  2675.     else
  2676.         Cursor++;
  2677.     RefPlusOne();        /* fast refresh for one char */
  2678.     return(CC_NORM);
  2679.     }
  2680.     return(CC_ERROR);
  2681. }
  2682.  
  2683. /*ARGSUSED*/
  2684. CCRETVAL
  2685. e_expand(c)
  2686.     int c;
  2687. {
  2688.     register Char *p;
  2689.     extern bool justpr;
  2690.  
  2691.     for (p = InputBuf; Isspace(*p); p++);
  2692.     if (p == LastChar)
  2693.     return(CC_ERROR);
  2694.  
  2695.     justpr++;
  2696.     Expand++;
  2697.     return(e_newline(0));
  2698. }
  2699.  
  2700. /*ARGSUSED*/
  2701. CCRETVAL
  2702. e_startover(c)
  2703.     int c;
  2704. {                /* erase all of current line, start again */
  2705.     ResetInLine();        /* reset the input pointers */
  2706.     return(CC_REFRESH);
  2707. }
  2708.  
  2709. /*ARGSUSED*/
  2710. CCRETVAL
  2711. e_redisp(c)
  2712.     int c;
  2713. {
  2714.     ClearLines();
  2715.     ClearDisp();
  2716.     return(CC_REFRESH);
  2717. }
  2718.  
  2719. /*ARGSUSED*/
  2720. CCRETVAL
  2721. e_cleardisp(c)
  2722.     int c;
  2723. {
  2724.     ClearScreen();        /* clear the whole real screen */
  2725.     ClearDisp();        /* reset everything */
  2726.     return(CC_REFRESH);
  2727. }
  2728.  
  2729. /*ARGSUSED*/
  2730. CCRETVAL
  2731. e_tty_int(c)
  2732.     int c;
  2733. {            
  2734. #ifdef _MINIX
  2735.     /* SAK PATCH: erase all of current line, start again */
  2736.     ResetInLine();        /* reset the input pointers */
  2737.     xputchar('\n');
  2738.     ClearDisp();
  2739.     return (CC_REFRESH);
  2740. #else /* !_MINIX */
  2741.     /* do no editing */
  2742.     return (CC_NORM);
  2743. #endif /* _MINIX */
  2744. }
  2745.   
  2746. /*ARGSUSED*/
  2747. CCRETVAL
  2748. e_insovr(c)
  2749.     int c;
  2750. {
  2751.     inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
  2752.     return(CC_NORM);
  2753. }
  2754.  
  2755. /*ARGSUSED*/
  2756. CCRETVAL
  2757. e_tty_dsusp(c)
  2758.     int c;
  2759. {
  2760.     /* do no editing */
  2761.     return(CC_NORM);
  2762. }
  2763.  
  2764. /*ARGSUSED*/
  2765. CCRETVAL
  2766. e_tty_flusho(c)
  2767.     int c;
  2768. {
  2769.     /* do no editing */
  2770.     return(CC_NORM);
  2771. }
  2772.  
  2773. /*ARGSUSED*/
  2774. CCRETVAL
  2775. e_tty_quit(c)
  2776.     int c;
  2777. {
  2778.     /* do no editing */
  2779.     return(CC_NORM);
  2780. }
  2781.  
  2782. /*ARGSUSED*/
  2783. CCRETVAL
  2784. e_tty_tsusp(c)
  2785.     int c;
  2786. {
  2787.     /* do no editing */
  2788.     return(CC_NORM);
  2789. }
  2790.  
  2791. /*ARGSUSED*/
  2792. CCRETVAL
  2793. e_tty_stopo(c)
  2794.     int c;
  2795. {
  2796.     /* do no editing */
  2797.     return(CC_NORM);
  2798. }
  2799.  
  2800. /*ARGSUSED*/
  2801. CCRETVAL
  2802. e_expand_history(c)
  2803.     int c;
  2804. {
  2805.     *LastChar = '\0';        /* just in case */
  2806.     c_substitute();
  2807.     return(CC_NORM);
  2808. }
  2809.  
  2810. /*ARGSUSED*/
  2811. CCRETVAL
  2812. e_magic_space(c)
  2813.     int c;
  2814. {
  2815.     *LastChar = '\0';        /* just in case */
  2816.     c_substitute();
  2817.     return(e_insert(' '));
  2818. }
  2819.  
  2820. /*ARGSUSED*/
  2821. CCRETVAL
  2822. e_inc_fwd(c)
  2823.     int c;
  2824. {
  2825.     patlen = 0;
  2826.     return e_inc_search(F_DOWN_SEARCH_HIST);
  2827. }
  2828.  
  2829.  
  2830. /*ARGSUSED*/
  2831. CCRETVAL
  2832. e_inc_back(c)
  2833.     int c;
  2834. {
  2835.     patlen = 0;
  2836.     return e_inc_search(F_UP_SEARCH_HIST);
  2837. }
  2838.  
  2839. /*ARGSUSED*/
  2840. CCRETVAL
  2841. e_copyprev(c)
  2842.     int c;
  2843. {
  2844.     register Char *cp, *oldc, *dp;
  2845.  
  2846.     if (Cursor == InputBuf)
  2847.     return(CC_ERROR);
  2848.     /* else */
  2849.  
  2850.     oldc = Cursor;
  2851.     /* does a bounds check */
  2852.     cp = c_prev_word(Cursor, InputBuf, Argument);    
  2853.  
  2854.     c_insert(oldc - cp);
  2855.     for (dp = oldc; cp < oldc && dp < LastChar; cp++)
  2856.     *dp++ = *cp;
  2857.  
  2858.     Cursor = dp;        /* put cursor at end */
  2859.  
  2860.     return(CC_REFRESH);
  2861. }
  2862.  
  2863. /*ARGSUSED*/
  2864. CCRETVAL
  2865. e_tty_starto(c)
  2866.     int c;
  2867. {
  2868.     /* do no editing */
  2869.     return(CC_NORM);
  2870. }
  2871.  
  2872. /*ARGSUSED*/
  2873. CCRETVAL
  2874. e_load_average(c)
  2875.     int c;
  2876. {
  2877.     PastBottom();
  2878. #ifdef TIOCSTAT
  2879.     if (ioctl(SHIN, TIOCSTAT, 0) < 0) 
  2880. #endif
  2881.     xprintf("Load average unavailable\n");
  2882.     return(CC_REFRESH);
  2883. }
  2884.  
  2885. /*ARGSUSED*/
  2886. CCRETVAL
  2887. v_chgmeta(c)
  2888.     int c;
  2889. {
  2890.     /*
  2891.      * Delete with insert == change: first we delete and then we leave in
  2892.      * insert mode.
  2893.      */
  2894.     return(v_action(DELETE|INSERT));
  2895. }
  2896.  
  2897. /*ARGSUSED*/
  2898. CCRETVAL
  2899. v_delmeta(c)
  2900.     int c;
  2901. {
  2902.     return(v_action(DELETE));
  2903. }
  2904.  
  2905.  
  2906. /*ARGSUSED*/
  2907. CCRETVAL
  2908. v_endword(c)
  2909.     int c;
  2910. {
  2911.     if (Cursor == LastChar)
  2912.     return(CC_ERROR);
  2913.     /* else */
  2914.  
  2915.     Cursor = c_endword(Cursor, LastChar, Argument);
  2916.  
  2917.     if (ActionFlag & DELETE)
  2918.     {
  2919.     Cursor++;
  2920.     c_delfini();
  2921.     return(CC_REFRESH);
  2922.     }
  2923.  
  2924.     RefCursor();
  2925.     return(CC_NORM);
  2926. }
  2927.  
  2928. /*ARGSUSED*/
  2929. CCRETVAL
  2930. v_eword(c)
  2931.     int c;
  2932. {
  2933.     if (Cursor == LastChar)
  2934.     return(CC_ERROR);
  2935.     /* else */
  2936.  
  2937.     Cursor = c_eword(Cursor, LastChar, Argument);
  2938.  
  2939.     if (ActionFlag & DELETE) {
  2940.     Cursor++;
  2941.     c_delfini();
  2942.     return(CC_REFRESH);
  2943.     }
  2944.  
  2945.     RefCursor();
  2946.     return(CC_NORM);
  2947. }
  2948.  
  2949. /*ARGSUSED*/
  2950. CCRETVAL
  2951. v_char_fwd(c)
  2952.     int c;
  2953. {
  2954.     Char ch;
  2955.  
  2956.     if (GetNextChar(&ch) != 1)
  2957.     return e_send_eof(0);
  2958.  
  2959.     srch_dir = CHAR_FWD;
  2960.     srch_char = ch;
  2961.  
  2962.     return v_csearch_fwd(ch, Argument, 0);
  2963.  
  2964. }
  2965.  
  2966. /*ARGSUSED*/
  2967. CCRETVAL
  2968. v_char_back(c)
  2969.     int c;
  2970. {
  2971.     Char ch;
  2972.  
  2973.     if (GetNextChar(&ch) != 1)
  2974.     return e_send_eof(0);
  2975.  
  2976.     srch_dir = CHAR_BACK;
  2977.     srch_char = ch;
  2978.  
  2979.     return v_csearch_back(ch, Argument, 0);
  2980. }
  2981.  
  2982. /*ARGSUSED*/
  2983. CCRETVAL
  2984. v_charto_fwd(c)
  2985.     int c;
  2986. {
  2987.     Char ch;
  2988.  
  2989.     if (GetNextChar(&ch) != 1)
  2990.     return e_send_eof(0);
  2991.  
  2992.     return v_csearch_fwd(ch, Argument, 1);
  2993.  
  2994. }
  2995.  
  2996. /*ARGSUSED*/
  2997. CCRETVAL
  2998. v_charto_back(c)
  2999.     int c;
  3000. {
  3001.     Char ch;
  3002.  
  3003.     if (GetNextChar(&ch) != 1)
  3004.     return e_send_eof(0);
  3005.  
  3006.     return v_csearch_back(ch, Argument, 1);
  3007. }
  3008.  
  3009. /*ARGSUSED*/
  3010. CCRETVAL
  3011. v_rchar_fwd(c)
  3012.     int c;
  3013. {
  3014.     if (srch_char == 0)
  3015.     return CC_ERROR;
  3016.  
  3017.     return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) : 
  3018.                       v_csearch_back(srch_char, Argument, 0);
  3019. }
  3020.  
  3021. /*ARGSUSED*/
  3022. CCRETVAL
  3023. v_rchar_back(c)
  3024.     int c;
  3025. {
  3026.     if (srch_char == 0)
  3027.     return CC_ERROR;
  3028.  
  3029.     return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) : 
  3030.                        v_csearch_back(srch_char, Argument, 0);
  3031. }
  3032.  
  3033. /*ARGSUSED*/
  3034. CCRETVAL
  3035. v_undo(c)
  3036.     int c;
  3037. {
  3038.     register int  loop;
  3039.     register Char *kp, *cp;
  3040.     Char temp;
  3041.     int     size;
  3042.  
  3043.     switch (UndoAction) {
  3044.     case DELETE|INSERT:
  3045.     case DELETE:
  3046.     if (UndoSize == 0) return(CC_NORM);
  3047.     cp = UndoPtr;
  3048.     kp = UndoBuf;
  3049.     for (loop=0; loop < UndoSize; loop++)    /* copy the chars */
  3050.         *kp++ = *cp++;            /* into UndoBuf   */
  3051.  
  3052.     for (cp = UndoPtr; cp <= LastChar; cp++)
  3053.         *cp = cp[UndoSize];
  3054.  
  3055.     LastChar -= UndoSize;
  3056.     Cursor   =  UndoPtr;
  3057.     
  3058.     UndoAction = INSERT;
  3059.     break;
  3060.  
  3061.     case INSERT:
  3062.     if (UndoSize == 0) return(CC_NORM);
  3063.     cp = UndoPtr;
  3064.     Cursor = UndoPtr;
  3065.     kp = UndoBuf;
  3066.     c_insert(UndoSize);        /* open the space, */
  3067.     for (loop = 0; loop < UndoSize; loop++)    /* copy the chars */
  3068.         *cp++ = *kp++;
  3069.  
  3070.     UndoAction = DELETE;
  3071.     break;
  3072.  
  3073.     case CHANGE:
  3074.     if (UndoSize == 0) return(CC_NORM);
  3075.     cp = UndoPtr;
  3076.     Cursor = UndoPtr;
  3077.     kp = UndoBuf;
  3078.     size = (int)(Cursor-LastChar); /*  NOT NSL independant */
  3079.     if (size < UndoSize)
  3080.         size = UndoSize;
  3081.     for(loop = 0; loop < size; loop++) {
  3082.         temp = *kp;
  3083.         *kp++ = *cp;
  3084.         *cp++ = temp;
  3085.     }
  3086.     break;
  3087.  
  3088.     default:
  3089.     return(CC_ERROR);
  3090.     }
  3091.  
  3092.     return(CC_REFRESH);
  3093. }
  3094.  
  3095. /*ARGSUSED*/
  3096. CCRETVAL
  3097. v_ush_meta(c)
  3098.     int c;
  3099. {
  3100.     return v_search(F_UP_SEARCH_HIST);
  3101. }
  3102.  
  3103. /*ARGSUSED*/
  3104. CCRETVAL
  3105. v_dsh_meta(c)
  3106.     int c;
  3107. {
  3108.     return v_search(F_DOWN_SEARCH_HIST);
  3109. }
  3110.  
  3111. /*ARGSUSED*/
  3112. CCRETVAL
  3113. v_rsrch_fwd(c)
  3114.     int c;
  3115. {
  3116.     if (patlen == 0) return(CC_ERROR);
  3117.     return(v_repeat_srch(searchdir));
  3118. }
  3119.  
  3120. /*ARGSUSED*/
  3121. CCRETVAL
  3122. v_rsrch_back(c)
  3123.     int c;
  3124. {
  3125.     if (patlen == 0) return(CC_ERROR);
  3126.     return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ? 
  3127.              F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
  3128. }
  3129.  
  3130. #ifdef notdef
  3131. void
  3132. MoveCursor(n)            /* move cursor + right - left char */
  3133.     int     n;
  3134. {
  3135.     Cursor = Cursor + n;
  3136.     if (Cursor < InputBuf)
  3137.     Cursor = InputBuf;
  3138.     if (Cursor > LastChar)
  3139.     Cursor = LastChar;
  3140.     return;
  3141. }
  3142.  
  3143. Char   *
  3144. GetCursor()
  3145. {
  3146.     return(Cursor);
  3147. }
  3148.  
  3149. int
  3150. PutCursor(p)
  3151.     Char   *p;
  3152. {
  3153.     if (p < InputBuf || p > LastChar)
  3154.     return 1;        /* Error */
  3155.     Cursor = p;
  3156.     return 0;
  3157. }
  3158. #endif
  3159.